using NUnit.Framework;
using dnAnalytics.LinearAlgebra;
using dnAnalytics.LinearAlgebra.Solvers;

namespace dnAnalytics.UnitTests.LinearAlgebra.Solvers
{
    [TestFixture]
    [Category("Managed")]
    public sealed class MatrixSolverConvergenceMonitorTest
    {
        private ConvergenceMonitor mMonitor = null;
        private int mMaximumIterationCount = 10;
        private double mConvergenceBoundary = 1;
        private double mMatrixNorm = 2;
        private double mVectorNorm = 1;
        
        private Vector mSolutionVector = null;
        private Vector mResidualVector = null;

        [SetUp]
        public void Setup()
        {
            mMonitor = new ConvergenceMonitor(mMaximumIterationCount,
                                                          mConvergenceBoundary,
                                                          mMatrixNorm);
            mMonitor.VectorNorm(mVectorNorm);
            mSolutionVector = VectorBuilder.CreateVector(2, VectorType.Dense);
            mResidualVector = VectorBuilder.CreateVector(2, VectorType.Dense);
        }

        [Test]
        public void StopCrossingIterationBounds()
        {
            // Add values to the solution and residual vectors
            // Make the residual values nice and big so that we are sure there
            // is no convergence
            mSolutionVector[0] = 1;
            mSolutionVector[1] = 2;
            
            mResidualVector[0] = 100;
            mResidualVector[1] = 1000;
            
            Assert.IsTrue(mMonitor.ShouldCalculationContinue(1, mSolutionVector, mResidualVector),"#01");
            Assert.IsFalse(mMonitor.ShouldCalculationContinue(11, mSolutionVector, mResidualVector),"#02");
        }

        [Test]
        public void StopCrossingConvergenceBounds()
        {
            // Add values to the solution and residual vectors
            // Make the residual values nice and small so that we are sure there
            // is convergence
            mSolutionVector[0] = 1;
            mSolutionVector[1] = 2;
            
            mResidualVector[0] = 0.01;
            mResidualVector[1] = 0.001;
            Assert.IsFalse(mMonitor.ShouldCalculationContinue(1, mSolutionVector, mResidualVector),"#01");
        }

        [Test]
        public void DoNotStop()
        {
            // Add values to the solution and residual vectors
            // Make the residual values nice and big so that we are sure there
            // is no convergence
            mSolutionVector[0] = 1;
            mSolutionVector[1] = 2;
            
            mResidualVector[0] = 100;
            mResidualVector[1] = 1000;
            Assert.IsTrue(mMonitor.ShouldCalculationContinue(1, mSolutionVector, mResidualVector),"#01");
        }
    }
}